//
//  UWGamesManager.m
//  Urban Words
//
//  Created by Tim Brandin on 2011-11-25.
//  Copyright (c) 2011 Sypreme. All rights reserved.
//

#import "UWGamesManager.h"

#import "UWApi.h"

#import "UWAppDelegate.h"

@implementation UWGamesManager

@synthesize ongoing, facebook, count;
@synthesize delegate;

static UWGamesManager *shared;

// Singleton

- (id)init {
    self = [super init];
    if (self) {
        // TODO: init database etc.. update to latest state from remote
        NSArray *dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        
        NSString *docsDir = [dirPath objectAtIndex:0];
        
        dbPath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"games.db"]];
        
        NSFileManager *filemgr = [NSFileManager defaultManager];
        
        if ([filemgr fileExistsAtPath:dbPath] == NO) {
            const char *dbpath = [dbPath UTF8String];
            
            if (sqlite3_open(dbpath, &gamesDB) == SQLITE_OK) {
                char *errMsg;
                const char *sql_stmt = "CREATE TABLE IF NOT EXISTS games (gameid INTEGER PRIMARY KEY, p1 VARCHAR(30), p2 VARCHAR(30), p1score INTEGER, p2score INTEGER, tiles VARCHAR(7), boardtiles VARCHAR(225), boardspecial VARCHAR(225), tilebag INT(11), finished INT(1), lastmove DATETIME, whosturn INTEGER)";
                
                if (sqlite3_exec(gamesDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) {
                    NSLog(@"Failed to create table");
                }
                
                sqlite3_close(gamesDB);
            }
            else {
                NSLog(@"Failed to open/create database");
            }
            
        }
        
        if (!facebook) {
            
            UWAppDelegate *appDelegate = (UWAppDelegate *)[[UIApplication sharedApplication] delegate];
            
            facebook = appDelegate.facebook;
        }
        
        [filemgr release];
    }
    
    return self;
}

- (void)refresh {
    [lastUpdated release];
    lastUpdated = nil;
    [self updateGames];
}

- (void)updateGames {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults objectForKey:@"FBAccessTokenKey"] 
        && [defaults objectForKey:@"FBExpirationDateKey"]
        && [defaults objectForKey:@"Fid"]) {
        
        if (lastUpdated == nil || [lastUpdated timeIntervalSinceNow] < -300) {
            
            lastUpdated = [[NSDate alloc] init];

            [UWApi read:[NSString stringWithFormat:@"games/%@?hej=1",[defaults valueForKey:@"Fid"]] 
               listener:self action:@selector(gamesLoaded:)];
        }
    }
}

- (void)gamesLoaded:(NSData *)data
{
    
    sqlite3_stmt *statement;
    
    const char *dbpath = [dbPath UTF8String];
    
    if (sqlite3_open(dbpath, &gamesDB) == SQLITE_OK) {
        
        NSDictionary *response = (NSDictionary *)[UWApi parseJson:data];
        
        if ([response objectForKey:@"games"]) {
            
            NSDictionary *gamesList = [[response objectForKey:@"message"] retain];
            
            BOOL changed = NO;
            
            
            for (NSObject *o in gamesList) {
                NSString *insertSQL = [NSString stringWithFormat:@"INSERT OR REPLACE INTO games (gameid, p1, p2, p1score, p2score, tiles, boardspecial, boardtiles, whosturn, lastmove, finished, tilebag) VALUES (\"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\")",  
                                       [o valueForKey:@"gameid"], 
                                       [o valueForKey:@"p1"],
                                       [o valueForKey:@"p2"],
                                       [o valueForKey:@"p1score"],
                                       [o valueForKey:@"p2score"],
                                       [o valueForKey:@"tiles"],
                                       [o valueForKey:@"boardspecial"],
                                       [o valueForKey:@"cB"],
                                       [o valueForKey:@"whosturn"],
                                       [o valueForKey:@"lastmove"],
                                       [o valueForKey:@"finished"],
                                       [o valueForKey:@"tilebag"]];
                
                const char *insert_stmt = [insertSQL UTF8String];
                
                sqlite3_prepare_v2(gamesDB, insert_stmt, -1, &statement, NULL);
                
                if (sqlite3_step(statement) == SQLITE_DONE) {
                    NSLog(@"added: %@, turn: %i", [o valueForKey:@"gameid"], [((NSString *)[o valueForKey:@"whosturn"]) intValue]);
                    changed = YES;
                }
                else {
                    //NSLog(@"Failed to add (Duplicate): %s", sqlite3_errmsg(gamesDB));
                }
                sqlite3_finalize(statement);
            }
            
            sqlite3_close(gamesDB);
            
            [[self delegate] gamesChanged:changed];
            
            [gamesList release];
        }
    }
}
 

+ (UWGamesManager *)sharedManager {
    if (shared == nil) {
        // allocate the shared istance, because it hasn't been done yet
        shared = [[super allocWithZone:NULL] init];
    }
    return shared;
}

+ (id)allocWithZone:(NSZone *)zone {
    return [[self sharedManager] retain];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)retain {
    return self;
}

- (NSUInteger)retainCount {
    return NSUIntegerMax;
}

- (oneway void)release {
    // Do nothing
}

- (id)autorelease {
    return self;
}

// End of singleton

- (UWGame *)getGame:(int)gameid
{
    // return a game from the Api here and store it in database.
    
    NSString *method = [NSString stringWithFormat:@"game/%i", gameid];
    
    [UWApi call:method withParams:nil delegate:self];
    
    return nil;
}

- (UWGame *)getGameAt:(NSInteger)row 
{
    
    // check last time games was updated, if old update it.
    
    // get game at row from local database
    sqlite3_stmt *statement;
    
    const char *dbpath = [dbPath UTF8String];
    UWGame *game = nil;
    
    if (sqlite3_open(dbpath, &gamesDB) == SQLITE_OK) {
        
        NSString *selectSQL = [NSString stringWithFormat:@"SELECT * FROM games WHERE finished = 0 ORDER BY gameid ASC LIMIT %i, 1", row];
        
        const char *select_stmt = [selectSQL UTF8String];
        
        if (sqlite3_prepare_v2(gamesDB, select_stmt, -1, &statement, NULL) == SQLITE_OK) {
            if (sqlite3_step(statement) == SQLITE_ROW) {
                game = [[UWGame alloc] init];
                game.gameid = sqlite3_column_int(statement, 0);
                game.boardSpecial = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 7)];
                game.board = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 6)];
                game.p1 = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
                game.p2 = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
                game.p1score = sqlite3_column_int(statement, 3);
                game.p2score = sqlite3_column_int(statement, 4);
                game.tilebag = sqlite3_column_int(statement, 8);
                game.opponent = [game.p1 isEqualToString:[[NSUserDefaults standardUserDefaults] valueForKey:@"Fid"]] ? game.p2 : game.p1;
                game.whosturn = sqlite3_column_int(statement, 11);
                game.tiles = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 5)];
                //game.lastMove = [NSDate ]sqlite3_column_int(statement, 10);
                
                NSLog(@"whosturn: %i", sqlite3_column_int(statement, 11));
            }
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(gamesDB);
    }
    
    return game;
}

- (NSArray *)getAllGameFriends
{
    sqlite3_stmt *statement;
    
    NSMutableArray *friends = nil;
    
    const char *dbpath = [dbPath UTF8String];
    
    if (sqlite3_open(dbpath, &gamesDB) == SQLITE_OK) {
        
        NSString *selectSQL = [NSString stringWithFormat:@"SELECT p1, p2 FROM games"];
        
        const char *select_stmt = [selectSQL UTF8String];
        
        if (sqlite3_prepare_v2(gamesDB, select_stmt, -1, &statement, NULL) == SQLITE_OK) {
            
            friends = [[NSMutableArray alloc] init];
            
            while (sqlite3_step(statement) == SQLITE_ROW) {
                
                NSString *p1 = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
                NSString *p2 = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
                
                [friends addObject:([p1 isEqualToString:[[NSUserDefaults standardUserDefaults] valueForKey:@"Fid"]] ? p2 : p1)];
                
            }
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(gamesDB);
    }
    
    return [NSArray arrayWithArray:friends];
}

- (NSInteger)ongoing 
{
    
    // check last time games was updated, if old update it.
    
    // count games in the local database
    
    sqlite3_stmt *statement;
    
    const char *dbpath = [dbPath UTF8String];
    int _count = 0;
    
    if (sqlite3_open(dbpath, &gamesDB) == SQLITE_OK) {
        
        NSString *selectSQL = [NSString stringWithFormat:@"SELECT COUNT(*) FROM games WHERE finished = 0"];
        
        const char *select_stmt = [selectSQL UTF8String];
        
        if (sqlite3_prepare_v2(gamesDB, select_stmt, -1, &statement, NULL) == SQLITE_OK) {
            if (sqlite3_step(statement)) {
                _count = sqlite3_column_int(statement, 0);
            }
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(gamesDB);
    }
    return ceil(_count/3.f);
}

- (NSInteger)count
{
    sqlite3_stmt *statement;
    
    const char *dbpath = [dbPath UTF8String];
    int _count = 0;
    
    if (sqlite3_open(dbpath, &gamesDB) == SQLITE_OK) {
        
        NSString *selectSQL = [NSString stringWithFormat:@"SELECT COUNT(*) FROM games"];
        
        const char *select_stmt = [selectSQL UTF8String];
        
        if (sqlite3_prepare_v2(gamesDB, select_stmt, -1, &statement, NULL) == SQLITE_OK) {
            if (sqlite3_step(statement)) {
                _count = sqlite3_column_int(statement, 0);
            }
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(gamesDB);
    }
    return ceil(_count/3.f);
}

- (void)clear 
{
    
    const char *dbpath = [dbPath UTF8String];
    
    if (sqlite3_open(dbpath, &gamesDB) == SQLITE_OK) {
        
        NSString *querystring = @"DELETE FROM games";
        
        const char *query = [querystring UTF8String];
        
        char *errMsg;
        
        if (sqlite3_exec(gamesDB, query, NULL, NULL, &errMsg) != SQLITE_OK) {
            NSLog(@"Failed to truncate games table %s", sqlite3_errmsg(gamesDB));
        }
        else {
           // NSLog(@"Success truncate games table");
            [lastUpdated release];
            lastUpdated = nil;
        }
    }
    
    sqlite3_close(gamesDB);
    
}

- (void)dealloc 
{
    [dbPath dealloc];
    //    [friendsDB dealloc];
    [super dealloc];
}

@end
